package com.boomsecret.lock;

import org.apache.commons.lang3.RandomUtils;

import java.util.Stack;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by wangjinliang on 2018/8/8.
 */
public class ConditionDemo {

    public static void main(String[] args) throws Exception {
        ConditionCollection collection = new ConditionCollection();
        new Thread(() -> {
            while (true) {
                try {
                    String result = collection.pop();
                    System.out.println("getResult --> " + result);
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }).start();

        Thread.sleep(5000);

        new Thread(() -> {
            while (true) {
                try {
                    int result = RandomUtils.nextInt();
                    collection.push("index:" + result);
                    System.out.println("setResult --> " + result);
                    Thread.sleep(800);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }).start();

    }
}

class ConditionCollection {
    private static final int maxLength = 10;
    private Stack<String> dataStack = new Stack<>();
    private ReentrantLock  lock = new ReentrantLock();
    private Condition emptyCondition = lock.newCondition();
    private Condition fullCondition = lock.newCondition();

    public String pop() {
        try {
            lock.lock();
            if (dataStack.size() == 0) {
                emptyCondition.await();
            }
            String result = dataStack.pop();
            fullCondition.signalAll();
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return null;
    }

    public void push(String value) {
        try {
            lock.lock();
            if (dataStack.size() > maxLength) {
                fullCondition.await();
            }
            dataStack.push(value);
            emptyCondition.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}
